package controller

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/mix-go/dotenv"
	"gorm.io/gorm"
	"math"
	"mytest/code"
	"mytest/database"
	"mytest/flower-order/model"
	"mytest/util"
	"os"
	"path/filepath"
	"runtime/debug"
	"strconv"
	"strings"
	"time"
)

type ImgController struct {
}

func (t *ImgController) Index(c *gin.Context) {
	var imgList []*model.Img
	var formHelper util.FormHelper
	params := [][]string{
		{"page", "int", "num|has"},
		{"limit", "int", "num|has"},
		{"path", "string-no-filter"},
	}
	paramMap, err := formHelper.Params(params, c)
	if err != nil {
		c.JSON(code.Success, util.ReturnError(code.ParamErr, err.Error()))
		return
	}
	conditions := " `file_path` = '/' "
	if len(paramMap["path"].(string)) > 0 {
		conditions = fmt.Sprintf(" `file_path` = '%s' ", paramMap["path"])
	}
	limit := paramMap["limit"].(int)
	page := paramMap["page"].(int)
	offset := (page - 1) * limit
	var count int64
	database.DB.Debug().Model(model.Img{}).Select("id").Where(conditions).Count(&count)
	err = database.DB.Debug().Model(model.Img{}).
		Where(conditions).
		Limit(limit).
		Offset(offset).
		Order("id desc").
		Find(&imgList).Error
	if err != nil {
		c.JSON(code.Success, util.ReturnError(code.SysErr, err.Error()))
		return
	}
	var images []map[string]interface{}
	for _, v := range imgList {
		path := v.FilePath + "/" + v.FileName
		if v.FilePath == "/" {
			path = v.FilePath + v.FileName
		}
		thumb := "/img" + path
		imgType := "image"
		if v.FileSize == 0 {
			thumb = ""
			imgType = "directory"
		}
		img := map[string]interface{}{
			"id":    v.Id,
			"thumb": thumb,
			"name":  v.FileName,
			"type":  imgType,
			"path":  path,
		}
		images = append(images, img)
	}
	data := map[string]interface{}{
		"images": images,
		"count":  count,
	}
	c.JSON(code.Success, util.ReturnSuccess(data))
	return
}

func (t *ImgController) Upload(c *gin.Context) {
	_, headers, err := c.Request.FormFile("file")
	if err != nil {
		c.JSON(code.Success, util.ReturnError(code.UploadrErr, err.Error()))
		return
	}
	//headers.Size 获取文件大小
	//if headers.Size > 1024*1024*2 {
	//	c.JSON(code.Success, util.ReturnError(code.UploadrErr, "文件太大了"))
	//	return
	//}
	// 检查图片后缀
	fileType := headers.Header.Get("Content-Type")
	if fileType != "image/jpeg" && fileType != "image/png" {
		c.JSON(code.Success, util.ReturnError(code.UploadrErr, "只支持jpg/png图片上传"))
		return
	}
	var subfix = ".jpg"
	if strings.HasSuffix(fileType, "png") {
		subfix = ".png"
	}

	// 上传文件到指定的路径
	fileName := strconv.Itoa(int(time.Now().Unix())) + subfix
	filePath := "/"
	var dst string
	uploadPath := strings.Trim(dotenv.Getenv("UPLOAD_PATH").String(), "/")
	dst = fmt.Sprintf("%s/%s/%s", uploadPath, filePath, fileName)

	err = c.SaveUploadedFile(headers, dst)
	if err != nil {
		c.JSON(code.Success, util.ReturnError(code.UploadrErr, err.Error()))
		return
	}
	fileInfo, err := util.CompressImg(dst, 630)
	if err != nil {
		fmt.Println(err.Error())
	}
	nowTimeStr := time.Now().Local().Format(util.TimeLayout)
	img := model.Img{
		CreatedAt: nowTimeStr,
		UpdatedAt: nowTimeStr,
		FileSize:  int64(math.Ceil(float64(fileInfo.Size()) / 1024)), //KB
		FileType:  fileType,
		FilePath:  filePath,
		FileName:  fileName,
	}
	err = database.DB.Debug().Model(model.Img{}).Create(&img).Error
	if err != nil {
		c.JSON(code.Success, util.ReturnError(code.SysErr, err.Error()))
		return
	}
	picUrl := "/img/" + fileName
	data := map[string]interface{}{
		"url": picUrl,
		"id":  img.Id,
	}
	c.JSON(code.Success, util.ReturnSuccess(data))
	return
}

func (t *ImgController) MultiUpload(c *gin.Context) {
	// 多文件
	form, _ := c.MultipartForm()
	files := form.File["file[]"]
	path := c.DefaultPostForm("path", "/")
	if path == "" {
		path = "/"
	}
	var fileList []*model.Img
	uploadPath := strings.Trim(dotenv.Getenv("UPLOAD_PATH").String(), "/")
	nowTimeStr := time.Now().Local().Format(util.TimeLayout)
	for _, file := range files {
		img := &model.Img{
			CreatedAt: nowTimeStr,
			UpdatedAt: nowTimeStr,
			FileName:  file.Filename,
			FileSize:  file.Size / 1024, //KB
			FileType:  file.Header.Get("Content-Type"),
			FilePath:  path,
		}

		var dst string
		if path == "/" {
			dst = fmt.Sprintf("%s/%s", uploadPath, file.Filename)
		} else {
			dst = fmt.Sprintf("%s/%s/%s", uploadPath, path, file.Filename)
		}
		fileList = append(fileList, img)
		// 上传文件到指定的路径
		c.SaveUploadedFile(file, dst)

	}
	err := database.DB.Debug().Model(model.Img{}).Create(fileList).Error
	if err != nil {
		c.JSON(code.Success, util.ReturnError(code.SysErr, err.Error()))
		return
	}
	c.JSON(code.Success, util.ReturnSuccess(fileList))
	go func(imgList []*model.Img) {
		defer func() {
			if e := recover(); e != nil {
				fmt.Printf("err:%v stack:%v", e, string(debug.Stack()))
			}
		}()
		for _, v := range fileList {
			var source string
			if len(v.FilePath) == 1 {
				source = fmt.Sprintf("%s/%s", uploadPath, v.FileName)
			} else {
				source = fmt.Sprintf("%s%s/%s", uploadPath, v.FilePath, v.FileName)
			}
			fileInfo, err := util.CompressImg(source, 630)
			if err != nil {
				fmt.Println(err.Error())
				continue
			} else {
				v.FileSize = fileInfo.Size()
			}
			newFileSize := math.Ceil(float64(fileInfo.Size()) / 1024)
			err = database.DB.Debug().Model(model.Img{}).Where("id=?", v.Id).Update("file_size", newFileSize).Error
			if err != nil {
				fmt.Println("更新压缩后图片信息失败,err:" + err.Error())
			}
		}
	}(fileList)
	return
}

func (t *ImgController) CreateFolder(c *gin.Context) {
	folder := c.PostForm("folder")
	path := c.DefaultPostForm("path", "")
	uploadPath := strings.Trim(dotenv.Getenv("UPLOAD_PATH").String(), "/")
	dstPath := uploadPath + "/" + path
	folderPath := filepath.Join(dstPath, folder)
	fileInfo, err := os.Stat(folderPath)
	if err != nil && !os.IsNotExist(err) {
		c.JSON(code.Success, util.ReturnError(code.SysErr, err.Error()))
		return
	}
	if fileInfo != nil && fileInfo.IsDir() {
		c.JSON(code.Success, util.ReturnError(code.SysErr, folder+" 文件夹已存在"))
		return
	}
	// 必须分成两步
	// 先创建文件夹
	err = os.Mkdir(folderPath, 0777)
	if err != nil {
		c.JSON(code.Success, util.ReturnError(code.SysErr, err.Error()))
		return
	}
	// 再修改权限
	err = os.Chmod(folderPath, 0777)
	if err != nil {
		c.JSON(code.Success, util.ReturnError(code.SysErr, err.Error()))
		return
	}
	nowTimeStr := time.Now().Local().Format(util.TimeLayout)
	if len(path) == 0 {
		path = "/"
	}
	img := model.Img{
		CreatedAt: nowTimeStr,
		UpdatedAt: nowTimeStr,
		FilePath:  path,
		FileName:  folder,
	}
	err = database.DB.Debug().Model(model.Img{}).Create(&img).Error
	if err != nil {
		c.JSON(code.Success, util.ReturnError(code.SysErr, err.Error()))
		return
	}
	c.JSON(code.Success, util.ReturnSuccess(img))
	return
}

//删除图片、文件夹
func (t *ImgController) Delete(c *gin.Context) {
	var img model.Img
	id := c.PostForm("id")
	if id == "" {
		c.JSON(code.Success, util.ReturnError(code.ParamErr, code.ErrMsg(code.ParamErr)))
		return
	}
	err := database.DB.Where("id=?", id).First(&img).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		c.JSON(code.Success, util.ReturnError(code.SysErr, err.Error()))
		return
	}
	isDir := false
	filePath := img.FilePath
	if img.FilePath != "/" {
		filePath += "/" + img.FileName
	} else {
		filePath += img.FileName
	}
	if img.FileSize == 0 {
		isDir = true
	}
	err = database.DB.Debug().Delete(&img).Error
	if err != nil {
		c.JSON(code.Success, util.ReturnError(code.SysErr, err.Error()))
		return
	}
	if isDir {
		err = database.DB.Debug().Where("file_path like ?", "%"+filePath).Delete(&model.Img{}).Error
		if err != nil {
			c.JSON(code.Success, util.ReturnError(code.SysErr, err.Error()))
			return
		}
	}
	path := strings.Trim(dotenv.Getenv("UPLOAD_PATH").String(), "/") + filePath
	_, err = os.Stat(path)
	if err != nil && os.IsNotExist(err) {
		c.JSON(code.Success, util.ReturnError(code.SysErr, "文件不存在"))
		return
	}
	if isDir {
		err = os.RemoveAll(path)
	} else {
		err = os.Remove(path)
	}
	if err != nil {
		c.JSON(code.Success, util.ReturnError(code.SysErr, err.Error()))
		return
	}

	c.JSON(code.Success, util.ReturnSuccess(nil))
	return
}
